import {FieldFormatTypes, NumericUnit} from "@/components/Charts/FieldFormatTypes";
import {IChartConfig, IDrill, IMetric, IModel} from "@/pages/SelfQuery/type";
import ICharts from "@/components/Charts/ICharts";
import {
  getLastLevelVisualTypeVal,
  getLevelVisualType,
  getModelTypeColumn,
  isLevelVisualTypeColumn
} from "@/pages/SelfQuery/utils";
import {IColumn} from "@/components/Charts/Table";
import {MODELTYPE} from "@/pages/SelfQuery/constants";
import {TooltipCfg} from '@antv/g2/lib/interface.d'


export function initTooltip(props: ICharts) {
  const tooltip: TooltipCfg = {
    showMarkers:true,
  }
  return tooltip
}

export function onShowTooltip(props: ICharts, ev: { x: any, y: any, title: string, items: any[] }) {
  const items = ev.items
  if (items && items.length) {
    for (let i in items) {
      const item = items[i]
      const {data} = item
      item.value = valueFormat(props, data[Object.keys(data)[0]])(item.value);
    }
  }
}

/**
 * 配置列字段的定义
 */
function setColDefs(props: ICharts) {
  const {data, filterConfigs, configs} = props;
  const {chartStyles} = configs
  let colDefs: any = {}
  let groups: Array<string> = filterConfigs.groups.filter((v: string) => v)
  //条线图直接返回
  if (chartStyles.bar && chartStyles.bar.barChart) {
    return {...colDefs, ...setChartValueFormat(props)}
  }
  let tickCount = 3
  if (data && data.length) {

    const keys = Object.keys(data[0])
    if (data[0][keys[0]].length > 15) {
      tickCount = 2
    }
  }
  let val = {
    tickCount: tickCount,
  }
  colDefs[groups[groups.length - 1]] = val

  return {...colDefs, ...setChartValueFormat(props)}
}

/**
 * 设置非表格图表数据的格式
 */
function setChartValueFormat(props: ICharts) {
  let formatter = (value: any) => value
  return {value: {formatter: formatter}}
}

/**
 * 数据格式的转换
 * @param props
 * @param column 字段列名或者别名
 */
function valueFormat(props: ICharts, column: string) {
  let formatter = (value: any) => value
  const {metrics} = props.configs
  if (!metrics || !metrics.length) {
    return formatter;
  }
  const metricList = metrics.filter((v: IMetric) => {
    const {name, field, agg} = v
    const {alias} = field
    return column == `${agg}(${getColumnFromName(name)})` || column == alias
  })
  if (!metricList.length) {
    return formatter;
  }
  const {format} = metricList[0]
  const {formatType} = format

  if (formatType == FieldFormatTypes.Percentage) {
    const decimalPlaces = format[FieldFormatTypes.Percentage].decimalPlaces
    formatter = (value: any) => {
      return `${Math.floor(value * 100 * Math.pow(10, decimalPlaces)) / Math.pow(10, decimalPlaces)}%`;
    }
  }
  if (formatType == FieldFormatTypes.Numeric) {
    const numeric = format[FieldFormatTypes.Numeric]
    const {decimalPlaces, unit, useThousandSeparator} = numeric
    formatter = (value: any) => {
      let formatterValue = parseFloat(formatByUnit(value, unit)).toFixed(decimalPlaces)
      formatterValue = formatByThousandSeperator(formatterValue, useThousandSeparator)
      return `${formatterValue}${unit == NumericUnit.None ? '' : unit}`;
    }
  }

  if (formatType == FieldFormatTypes.Currency) {
    const currency = format[FieldFormatTypes.Currency]
    const {decimalPlaces, unit, prefix, suffix, useThousandSeparator} = currency
    formatter = (value: any) => {
      let formatterValue = parseFloat(formatByUnit(value, unit)).toFixed(decimalPlaces)
      formatterValue = formatByThousandSeperator(formatterValue, useThousandSeparator)
      return `${prefix}${formatterValue}${unit == NumericUnit.None ? '' : unit}${suffix}`;
    }
  }
  return formatter
}

function formatByThousandSeperator(value: any, useThousandSeparator: boolean) {
  if (isNaN(+value) || !useThousandSeparator) {
    return value
  }
  const parts = value.toString().split('.')
  parts[0] = parts[0].replace(/\B(?=(\d{3})+(?!\d))/g, ',')
  const formatted = parts.join('.')
  return formatted
}

/**
 * 坐标轴配置
 */
function setAxis(props: ICharts) {
  const {filterConfigs} = props;
  let groups: Array<string> = filterConfigs.groups.filter((v: string) => v)
  return [{
    field: groups[groups.length - 1], config: {
      label: function label(text: any, index: any, total: any) {
        const textCfg: any = {};
        if (index === 0) {
          textCfg.textAlign = 'left';
        } else if (index === total - 1) {
          textCfg.textAlign = 'right';
        }
        return textCfg;
      }
    }
  }]
}

/**
 * 数据加工
 * @param datas
 * @param props
 */
function dataProcess(datas: Array<any>, props: ICharts) {
  const {model} = props.configs
  //展示长路径的叶子节点
  datas = datas.map(data => {
    const keys = Object.keys(data)
    keys.map((key: string) => {
      //固定添加维度
      if (isLevelVisualTypeColumn(key, model)) {
        data[`${key}@VisualType@${getLevelVisualType(key, model)}`] = data[key]
        data[key] = getLastLevelVisualTypeVal(data[key])
      }
    })
    return data
  })
  datas = setCustom(datas, props);
  return datas
}

/**
 * 数据格式转化
 * @param datas
 * @param props
 */
function dataValueFormat(props: ICharts) {
  let datas = props.data
  if (datas && datas.length) {
    //数据格式设置
    let list: any = datas.map((val) => {
      let value: any = {}
      const keys = Object.keys(val)
      keys.forEach(((v: string) => {
        value[v] = valueFormat(props, v)(val[v])
      }))
      return value
    })
    return list
  }
  return datas
}

/**
 * 维度自定义排序
 * datas 封装后的数据
 */
function setCustom(datas: Array<any>, props: ICharts) {
  const {configs, filterConfigs} = props;
  let groups: Array<string> = filterConfigs.groups.filter((v: string) => v)
  //下钻不需要排序
  if (groups.length > 1) {
    return datas;
  }
  const {sort, name} = configs.cols[0]
  if (sort) {
    const sortType = sort.sortType
    if (sortType == 'custom') {
      let list: Array<{}> = []
      sort.custom.sortList.forEach((s: any) => {
        datas.forEach((data: any) => {
          if (s == data[name]) {
            list.push(data)
          }
        })
      })
      return list;
    }
  }
  return datas;
}

/**
 * 配置重构（非饼状图）
 */
function setConfigs(props: ICharts) {
  const {filterConfigs} = props;
  let groups: Array<string> = filterConfigs.groups.filter((v: string) => v)
  const chartOnEvent = (chart:any)=> {
    chart.interaction('element-highlight-by-x', {
      start: [{ trigger: 'element:click', action: 'element-highlight-by-x:clear' }],
      end: [{ trigger: 'element:click', action: 'element-highlight-by-x:highlight' }],
    });
    chart.interaction('active-region', {
      start: [{ trigger: 'plot:click', action: 'active-region:hide' }],
      end: [{ trigger: 'plot:click', action: 'active-region:show' }],
    });
    // tooltip 显示时触发
    chart.on('tooltip:show', (ev:{ x: any, y: any, title: string, items: any[],tooltip:any }) => {
      onShowTooltip(props,ev)
    });
  }
  return {
    tooltip: initTooltip(props),
    position: `${groups[groups.length - 1]}*value`,
    colDefs: setColDefs(props),
    axis: setAxis(props),
    onEvent:chartOnEvent
  }
}

/**
 * 封装数据
 */
function setData(props: ICharts) {
  let list: any = []
  const {configs, filterConfigs, data} = props;
  // let data = dataValueFormat(props);
  let groups: Array<string> = filterConfigs.groups.filter((v: string) => v)
  const {metrics, drills} = configs
  //维度字段
  const name = groups[groups.length - 1]
  data.forEach((v: any) => {
    metrics.forEach((metric: any) => {
      let metricName = `${metric.agg}(${metric.name.split("@")[0]})`
      let alias = getAlias(metric, drills)
      let val: any = {type: alias, value: !v[metricName] ? 0 : v[metricName]}
      val[name] = v[name]
      list.push(val)
    })
  })
  return dataProcess(list, props)
}

/**
 * 封装数据(层叠百分比数据)，条线图，柱状图
 */
function setDataPercent(props: ICharts) {
  let list: any = []
  const {configs, filterConfigs, data} = props;
  // let data = dataValueFormat(props);
  let groups: Array<string> = filterConfigs.groups.filter((v: string) => v)
  const {metrics, drills} = configs
  //维度字段
  const name = groups[groups.length - 1]
  data.forEach((v: any) => {
    let dataSum = 0
    metrics.forEach((metric: any) => {
      let metricName = `${metric.agg}(${metric.name.split("@")[0]})`
      const value = !v[metricName] || v[metricName] == '' ? 0 : v[metricName]
      dataSum = dataSum + value
    })
    metrics.forEach((metric: any) => {
      let metricName = `${metric.agg}(${metric.name.split("@")[0]})`
      let alias = getAlias(metric, drills)
      const value = !v[metricName] || v[metricName] == '' ? 0 : v[metricName]
      const percent = !(value / dataSum) ? 0 : value / dataSum
      let val: any = {type: alias, value: value, percent: percent}
      //固定添加维度
      val[name] = v[name]
      list.push(val)
    })
  })
  return dataProcess(list, props)
}

/**
 * 封装数据(饼状图)
 */
function setDataPie(props: ICharts) {
  let list: any = []
  const {configs, filterConfigs, data} = props;
  // let data = dataValueFormat(props);
  let groups: Array<string> = filterConfigs.groups.filter((v: string) => v)
  const {metrics, drills} = configs
  //维度字段
  const name = groups[groups.length - 1]
  data.forEach((v: any) => {
    metrics.forEach((metric: any) => {
      let metricName = `${metric.agg}(${metric.name.split("@")[0]})`
      let alias = getAlias(metric, drills)
      let val: any = {type: alias, value: !v[metricName] ? 0 : v[metricName], const: 'const'}
      //固定添加维度
      val[name] = v[name]
      list.push(val)
    })
  })
  return dataProcess(list, props)
}

function formatByUnit(value: any, unit: string) {
  const numericValue = +value
  if (isNaN(numericValue)) {
    return value
  }

  let exponent = 0

  switch (unit) {
    case NumericUnit.TenThousand:
      exponent = 4
      break
    case NumericUnit.OneHundredMillion:
      exponent = 8
      break
    case NumericUnit.Thousand:
      exponent = 3
      break
    case NumericUnit.Million:
      exponent = 6
      break
    case NumericUnit.Giga:
      exponent = 9
      break
  }
  return numericValue / Math.pow(10, exponent)
}

/**
 * 获取别名
 * @param metric
 */
function getAlias(metric: IMetric, drills: Array<IDrill>) {
  const {field, name} = metric
  const column = getColumnFromName(name)
  if (field.alias == '') {
    if (drills) {
      const drillArr = drills.filter(value => value.name == column)
      if (drillArr.length) {
        const drill = drillArr[0]
        if (drill.field.alias != '') {
          return drill.field.alias
        }
      }
    }
    return column
  }
  return field.alias
}

const getColumnFromName = (name: string) => name.toString().split('@davinci@')[0]

/**
 * 是否KPI指标
 * @param data
 * @param columns
 */
function isKpiChart(data: Array<any>, columns: Array<IColumn>, model: IModel) {
  let isKpi = data.length == 1 && columns.length === 2 && columns.filter(value => {
    const {key} = value
    const modelType = getModelTypeColumn(key, model)
    return MODELTYPE.Category != modelType
  }).length == 2
  return isKpi
}

/**
 * 是否是条线图
 * @param configs
 */
function isBarChart(configs: IChartConfig) {
  return configs.chartStyles.bar.barChart
}

export {
  setData,
  setConfigs,
  setDataPercent,
  setColDefs,
  setAxis,
  setDataPie,
  formatByUnit,
  isKpiChart,
  isBarChart,
  valueFormat,
  dataValueFormat
}
